#include <avr/wdt.h>

// -------------------
// DEBUG MODE
//#define DEBUG_SER
#define DEBUG_SER2
#define DEBUG_SER_DLY 200
#define DEBUG_LED

// -------------------
// -- INTERFACE

#define HAS_BGTEMPSENSOR
#define HAS_THERMOELECTRIC
#define HAS_ACTTEMPSENSOR

// --------------------
// --  ETC

/* Constant */
#define LED_DLY 5


/*   PID   */
#define PID_KP 1
#define PID_KI 1
#define PID_KD 1

// --------------------
// --  DEBUG_LED
#ifdef DEBUG_LED

/* Pinout */
#define LED_DBG 17

/* Constant */
#define DEBUG_DLY LED_DLY

#define DBGINIT 2
#define RECEIVE_DEL_DBG 1
#define SETTEMP_DBG_NOREP 0
#define SETTEMP_DBG_REP 2
#define SETPID_DBG 3
#define SETID_DBG 4

void DBG_LEDinit(){
    /*pinMode(LED_DBG, OUTPUT);
    DBG_LEDblink(DBGINIT);
    digitalWrite(LED_DBG, HIGH);*/
}

void DBG_LEDblink(int x){
    /*for (int i = 0; i < x; ++i){
        digitalWrite(LED_DBG, LOW);
        delayMicroseconds(DEBUG_DLY);
        digitalWrite(LED_DBG, HIGH);
        delayMicroseconds(DEBUG_DLY);
    }*/
}

#endif

// --------------------
// --  EEPROM
#include <EEPROM.h>

/* Constant */
//  ADDRESS VARIABEL DI EEPROM
const uint8_t ABSIS_ADD = 1;
const uint8_t ORDINAT_ADD = 4;



// --------------------
// --  RS-485

/* Pinout */
#define CTR_485 8
#define LED485_ENABLE

#ifdef LED485_ENABLE
#define LED_485 13
#endif

/* Constant */
#define RX485 0
#define TX485 1

void set485Mode(char mode){
    if (mode) {
        digitalWrite(CTR_485, HIGH);
#ifdef LED485_ENABLE
        digitalWrite(LED_485, HIGH);
#endif
    } else {
        digitalWrite(CTR_485, LOW);
#ifdef LED485_ENABLE
        digitalWrite(LED_485, LOW);
#endif
    }
}

void init485(){
#ifdef LED485_ENABLE
    pinMode(LED_485, OUTPUT); 
#endif
    pinMode(CTR_485, OUTPUT);  
    #ifdef LED485_ENABLE
    for (int i=0; i < 3; ++i){
        digitalWrite(LED_485, HIGH);
        delay(50);
        digitalWrite(LED_485, LOW);
        delay(50);
    }  
    #endif 
    set485Mode(RX485);
}

// --------------------
// --  plateConfig

#include "plateConf.h"

plateConf cfg;

// --------------------
//#include "serialProcessor.h"
//#include "peltierControl.h"

void setup(){
    // ---------
    // -- INIT WATCHDOG
    wdt_enable(WDTO_500MS);

    // ----------
    // -- INIT SERIAL
    Serial.begin(115200); 
    
    // ----------
    // -- INIT 485
    init485();
    set485Mode(RX485);
    
    // ----------
    // -- INIT CONFIG
    initPlateConf(&cfg);    
    int temp;
    
    temp =  EEPROM.read(ABSIS_ADD);
    temp = (temp == 255)?0:temp;
    setAbsis(&cfg , 1);
    temp =  EEPROM.read(ORDINAT_ADD);
    temp = (temp == 255)?0:temp;
    setOrdinat(&cfg , 2);
    setKp(&cfg , PID_KP);
    setKi(&cfg , PID_KI);
    setKd(&cfg , PID_KD); 

    
    #ifdef HAS_BGTEMPSENSOR
    MLX_init();
    #endif
    
    #ifdef HAS_THERMOELECTRIC
    peltierInit();
    #endif
    
    // ----------
    // -- DEBUG_LED
    #ifdef DEBUG_LED
    DBG_LEDinit();   
    #endif

}

void loop(){ 
    wdt_reset();

    // ----------
    // -- SERIAL PARSER
    processSerial();
	
    wdt_reset();
    
    #ifdef DEBUG_SER
    static long debug_now = 0;
    static long debug_next = debug_now + DEBUG_SER_DLY;
    debug_now = millis();
    if (debug_next < debug_now){
        Serial.println();
        Serial.print("--  (");
        Serial.print(getAbsis(cfg));
        Serial.print(" , ");
        Serial.print(getOrdinat(cfg));
        Serial.print(" ) ");
    }
    #endif
    
    // ----------
    // -- UPDATE ACTTEMP
    #ifdef HAS_BGTEMPSENSOR
    // Update Data Sensor 
    int BGTemp = MLX_read();
    setBgTemp(&cfg, BGTemp * 2);
    
    #ifdef DEBUG_SER
    if (debug_next < debug_now){ 
        Serial.print("  ");
        Serial.print(BGTemp);
    }
    #endif
    
    #else
    // DATA DUMMY (TIDAK ADA SENSOR)
    setBgTemp(&cfg, getOrdinat(cfg) * 10 + getAbsis(cfg));
    #endif    
    
    // ----------
    // -- UPDATE BGTEMP
    #ifdef HAS_ACTTEMPSENSOR
    // Update Data Sensor     
    int actTemp = readActTempSensor();
    setActTemp(&cfg, actTemp * 2);
            
    #ifdef DEBUG_SER
    if (debug_next < debug_now){ 
        Serial.print("  ");
        Serial.print(actTemp);
    }
    #endif
    
    #else
    // DATA DUMMY (TIDAK ADA SENSOR)    
    setActTemp(&cfg, getAbsis(cfg) * 10 + getOrdinat(cfg));
    #endif
    
    wdt_reset();
        
    // ----------
    // -- THERMOELECTRIC PID CONTROL LOOP
    #ifdef HAS_THERMOELECTRIC
    int _setPoint = getTargetTemp(cfg) / 2;
    int _actual = getActTemp(cfg) / 2;
    peltierControl(_setPoint, _actual);    
    
    #ifdef DEBUG_SER2
    static long debug_now = 0;
    static long debug_next = debug_now + DEBUG_SER_DLY;
    debug_now = millis();
    if (debug_next < debug_now){ 
        Serial.println();
        Serial.print(" -- SET : ");
        Serial.print(_setPoint);
        Serial.print(" -- ACT : ");
        Serial.print(_actual);
    }
    #endif
    
    #endif
   
    #ifdef DEBUG_SER
    if (debug_next < debug_now){ 
        debug_next = debug_now + DEBUG_SER_DLY;
    }
    #endif
    
    #ifdef DEBUG_SER2
    if (debug_next < debug_now){ 
        debug_next = debug_now + DEBUG_SER_DLY;
    }
    #endif
    
}


